Since your blog content will grow, Fuse.js is the industry standard for adding fuzzy search to static sites. It handles typos and partial matches gracefully.
Here is the step-by-step to upgrade your current search to a fuzzy one.
1. Add the Fuse.js Library
In your _includes/layout.njk, add the Fuse.js script tag before your own search script:
HTML
<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
2. Update the Search Logic
Replace your previous search script with this version. It initializes the "Fuse" index and uses its search algorithm instead of the basic .includes() method.
JavaScript
const searchInput = document.getElementById('search-input');
const resultsList = document.getElementById('search-results');
let fuse;
// 1. Fetch the index and initialize Fuse
fetch('/search.json')
.then(response => response.json())
.then(data => {
fuse = new Fuse(data, {
keys: ['title', 'tags', 'date'], // The fields to search in
threshold: 0.3, // 0.0 = perfect match, 1.0 = match anything. 0.3 is the "sweet spot"
distance: 100 // How far the typo can be from the original word
});
});
// 2. Perform Fuzzy Search
searchInput.addEventListener('input', (e) => {
const term = e.target.value;
resultsList.innerHTML = '';
if (term.length < 2) {
resultsList.style.display = 'none';
return;
}
// Use Fuse to search
const results = fuse.search(term);
if (results.length > 0) {
resultsList.style.display = 'block';
results.forEach(result => {
const post = result.item; // Fuse wraps results in an 'item' object
const li = document.createElement('li');
const tagList = Array.isArray(post.tags)
? post.tags.filter(t => t !== 'post').join(', ')
: '';
li.innerHTML = `
<a href="${post.url}">${post.title}</a><br>
<small>${post.date} ${tagList ? 'in ' + tagList : ''}</small>
`;
resultsList.appendChild(li);
});
} else {
resultsList.style.display = 'block';
resultsList.innerHTML = '<li>No matches found</li>';
}
});
---
How Fuzzy Logic Changes the User Experience
- Typo Tolerance: If a user types "Eleventi", Fuse.js will still find "Eleventy".
- Weighted Search: You can actually tell Fuse that the Title is more important than the Tags by adding a weight: keys: [{ name: 'title', weight: 2 }, 'tags'].
- Threshold: If the search is too "loose" (showing irrelevant things), change threshold: 0.3 to 0.2. If it’s too strict, move it toward 0.4.
3. Verify the JSON Data
Make sure your search.json (generated by search-index.json.njk) still contains the title, tags, and date fields as separate keys so Fuse can scan them individually.
4. Push to Cloudflare
Bash
git add .
git commit -m "Upgrade to fuzzy search with Fuse.js"
git push origin main
Now that your search is quite advanced, would you like to add "Search Highlighting" so the matched letters are bolded in the results?